﻿#include "function_dl_3.h"

bool isInsideEllipse(const QPoint &point, const QPoint &center, int semiMajorAxis, int semiMinorAxis) {
	double dx = point.x() - center.x();
	double dy = point.y() - center.y();
	double distanceSquared = dx * dx / (semiMajorAxis * semiMajorAxis) + dy * dy / (semiMinorAxis * semiMinorAxis);
	return distanceSquared <= 1.0;
}

Function_dl_3::Function_dl_3(QDialog* parent, QSettings* qsettings, QString section,int camera_index,int detection_index) : QDialog(parent)
{
	QSettings* m_settings_para = new QSettings(QCoreApplication::applicationDirPath() +"/para" +"/para.ini", QSettings::IniFormat);
	m_settings_para->setIniCodec("UTF-8");
	//m_save_image_dir = m_settings_para->value("para/m_save_image_dir", "").toString();


    m_qsettings = qsettings;
    m_section = section;
	m_camera_index = camera_index;
	m_detection_index = detection_index;

    this->setWindowTitle(("Deep Learning"));
    QRect desktop_rect = QApplication::desktop()->geometry();
    double ratio_x = desktop_rect.width()/1920.0;
    double ratio_y = desktop_rect.height()/1080.0;

    move(0,0);
    setFixedSize(1920*ratio_x,1010*ratio_y);



    m_view = new QtQGraphicsView(this);
    m_view->setGeometry(660 * ratio_x, 0, 1000 * 1.25 * ratio_x, 800 * 1.25 * ratio_y);

	connect(m_view->m_pixmapItem, &QtQGraphicsPixmapItem::drawRectangleFinish, this, [=](QGraphicsItem* p, int draw_type)
	{
		if (draw_type == 1)
			m_vector_graphics_shape_rectangle.push_back((GraphicsShapeRectangleCirce*)p);
        if (draw_type == 2)
        {
            GraphicsShapeRectangleCirce* p_ear = (GraphicsShapeRectangleCirce*)p;
            p_ear->m_message = "ear" + QString::number(m_vector_rectangle_ear.size());
            m_vector_rectangle_ear.push_back((GraphicsShapeRectangleCirce*)p);

        }

	});
    

    QSize control_size(220*ratio_x,40*ratio_y);

    QWidget* p = new QWidget(this);
    p->move(0*ratio_x,0*ratio_y);
    p->setFixedSize(600*ratio_x,1010*ratio_y);

    QGridLayout *qgridLayout = new QGridLayout();
    p->setLayout(qgridLayout);

    int index = 0;

    QSize ButtonSize(220 * ratio_x, 40 * ratio_y);
    m_pushbutton_open_model = new QPushButton();
    m_pushbutton_open_model->setFixedSize(control_size);
    m_pushbutton_open_model->setText("SetModelPath");
    connect(m_pushbutton_open_model, &QPushButton::clicked, this, [=]() {
        QString filename;
        filename = QFileDialog::getOpenFileName(this,
            tr("Select Model"),
            "",
            tr("(*.proj)"));
//            tr("(*.a *.b)"));
        if (filename.isEmpty())
        {
            return;
        }
        RetrainedModelFileName = filename;
        m_qlabel_model_path->setText(RetrainedModelFileName);

    });

    qgridLayout->addWidget(m_pushbutton_open_model, index, 0);

	index++;
	QPushButton* p_QPushButton ;
	
	m_qlabel_model_path = new QLabel();
	m_qlabel_model_path->setText("");
	m_qlabel_model_path->setFixedSize(600 * ratio_x, 40 * ratio_y);
	qgridLayout->addWidget(m_qlabel_model_path, index, 0);
	index++;

	if (m_camera_index == 0 || m_camera_index == 1 || m_camera_index == 2)
	{
		p_QPushButton = new QPushButton(this);
		p_QPushButton->setFixedSize(control_size);
		p_QPushButton->setText("Draw ROI");
		connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
			m_view->m_pixmapItem->m_shape_type = 1;
			m_view->m_pixmapItem->m_color = Qt::blue;
			m_view->m_pixmapItem->m_bool_filled = false;
		});
		qgridLayout->addWidget(p_QPushButton, index, 0);


		p_QPushButton = new QPushButton(this);
		p_QPushButton->setFixedSize(control_size);
		p_QPushButton->setText("Delete ROI");
		qgridLayout->addWidget(p_QPushButton, index, 1);
		connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
			for (GraphicsShapeRectangleCirce *item : m_vector_graphics_shape_rectangle) {
				m_view->scene()->removeItem(item);
				delete item;
			}
			m_vector_graphics_shape_rectangle.clear();
		});
		index++;
	}

    m_qcombox_unuse_use_ear = new QComboBox(this);
    m_qcombox_unuse_use_ear->setFixedSize(control_size);
    m_qcombox_unuse_use_ear->addItem("Ear Stop");
    m_qcombox_unuse_use_ear->addItem("Ear Start");
    qgridLayout->addWidget(m_qcombox_unuse_use_ear, index, 0);
    index++;
	if (m_camera_index == 0 || m_camera_index == 1 || m_camera_index == 2)
	{
		m_qcombox_unuse_use_ear->setVisible(false);
	}
	if (m_detection_index!=0)
	{
		m_qcombox_unuse_use_ear->setVisible(false);
	}
	if (m_camera_index == 3 || m_camera_index == 4)
	{
		if (m_detection_index == 0)
		{
			p_QPushButton = new QPushButton(this);
			p_QPushButton->setFixedSize(control_size);
			p_QPushButton->setText("Draw Ear");
			connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
				m_view->m_pixmapItem->m_shape_type = 2;
				m_view->m_pixmapItem->m_color = Qt::darkYellow;
				m_view->m_pixmapItem->m_bool_filled = false;
			});
			qgridLayout->addWidget(p_QPushButton, index, 0);


			p_QPushButton = new QPushButton(this);
			p_QPushButton->setFixedSize(control_size);
			p_QPushButton->setText("Delete Ear");
			qgridLayout->addWidget(p_QPushButton, index, 1);
			connect(p_QPushButton, &QPushButton::clicked, this, [=]() {
				for (GraphicsShapeRectangleCirce *item : m_vector_rectangle_ear) {
					m_view->scene()->removeItem(item);
					delete item;
				}
				m_vector_rectangle_ear.clear();
			});
			index++;
		}
	}
	
	

    m_pushbutton_show_orign_image = new QPushButton(this);
    m_pushbutton_show_orign_image->setFixedSize(control_size);
    m_pushbutton_show_orign_image->setText("ShowOrign");
    connect(m_pushbutton_show_orign_image, &QPushButton::clicked, this,[=]() {
        QImage q_image = matToQImage(m_image);
        m_view->setImage(q_image,"");
        return true;
    });
    qgridLayout->addWidget(m_pushbutton_show_orign_image, index,0);

    m_pushbutton_detection = new QPushButton(this);
    m_pushbutton_detection->setFixedSize(control_size);
    m_pushbutton_detection->setText("Detection");
    connect(m_pushbutton_detection, &QPushButton::clicked, this, &Function_dl_3::detectionImage);
    qgridLayout->addWidget(m_pushbutton_detection, index,1);
    index++;

	m_pushbutton_save_parameter = new QPushButton(this);
	m_pushbutton_save_parameter->setFixedSize(control_size);
	m_pushbutton_save_parameter->setText("Save");
	connect(m_pushbutton_save_parameter, &QPushButton::clicked, this, &Function_dl_3::saveParameter);
	qgridLayout->addWidget(m_pushbutton_save_parameter, index, 0);

    m_pushbutton_return = new QPushButton(this);
    m_pushbutton_return->setFixedSize(control_size);
    m_pushbutton_return->setText("Exit");
    qgridLayout->addWidget(m_pushbutton_return, index, 1);
    connect(m_pushbutton_return, &QPushButton::clicked, this, [=]() {
        this->hide();
        });
	index++;
    

    m_qwidget_dl_para1 = new  QWidgetDlPara1(nullptr,m_section);
    m_qwidget_dl_para1->setFixedSize(600 * ratio_x, 170 * ratio_y);
    qgridLayout->addWidget(m_qwidget_dl_para1, index, 0);
    index++;
	if ( m_camera_index == 3 || m_camera_index == 4)
	{
		if (m_detection_index == 0)
		{
			m_qwidget_dl_para2 = new  QWidgetDlPara2(nullptr, m_section + "_ear");
			m_qwidget_dl_para2->setFixedSize(600 * ratio_x, 430 * ratio_y);
			qgridLayout->addWidget(m_qwidget_dl_para2, index, 0);
		}
	}

    loadParameter();

}

Function_dl_3::~Function_dl_3()
{
    ;
}

int Function_dl_3::detection(Mat image, QString& message)
{
    m_image = image;
    if(image.empty())
    {
        message = "image empty ";
        return -1;
    }

    if(m_state==false)
    {
        return 0;
    }


    vector<vector<AIResult>> result_all;
    int result = m_dl->predictImage(image,result_all);
	if (result < 0)
	{
		message = "image size wrong or node name wrong";
		return 0;
	}

	result_defect.clear();

	if (result_all.size() == 0)
	{
		return 1;
	}
	///第一步遍历一遍所有缺陷，找到未知的缺陷

	for (auto& obj : result_all[0]) {
		int standard_index = -1;
		for (auto& obj_standard : m_vector_defect_standard)
		{
			if (obj.name == obj_standard.name)
			{
				standard_index = 0;
				if (obj.threshold_score < obj_standard.threshold_score)
				{
					
				
					break;
				}

                if (obj.area < obj_standard.threshold_size)
                {
                    break;
                }


			
				
                if (m_vector_graphics_shape_rectangle.size() >= 1){

					if (obj.x < column1 || obj.x > column2 || obj.y < row1 || obj.y > row2)
					{
						break;
					}
					
				}

//				if (m_vector_rectangle_ear.size() >= 1) {

//					if (obj.x > column1 && obj.x < column2 && obj.y > row1 && obj.y < row2)
//					{
//						break;
//					}

//				}

				result_defect.push_back(obj);
                message += QString::fromLocal8Bit(obj.name.c_str())  + ":size" + QString::number(obj.area) + "score" + QString::number(obj.threshold_score) + "\n";
				break;
			}
		}	
		if (standard_index == -1)
		{
			if (m_vector_graphics_shape_rectangle.size() >= 1) {

				if (obj.x < column1 || obj.x > column2 || obj.y < row1 || obj.y > row2)
				{
					break;
				}

			}

//            if (m_vector_rectangle_ear.size() >= 1) {

//                QPoint centor((m_ear_column1*0.5 + m_ear_column2 * 0.5), (m_ear_row1*0.5 + m_ear_row2 * 0.5));
//                int semiMajorAxis = max(abs(m_ear_row2*0.5 - m_ear_row1 * 0.5), abs(m_ear_column2*0.5 - m_ear_column1 * 0.5));
//                int semiMinorAxis = min(abs(m_ear_row2*0.5 - m_ear_row1 * 0.5), abs(m_ear_column2*0.5 - m_ear_column1 * 0.5));
//                bool bool_result = isInsideEllipse(QPoint(obj.x,obj.y), centor, semiMajorAxis, semiMinorAxis);
//                if (bool_result)
//                    break;
//                /*if (obj.x > m_ear_column1 && obj.x < m_ear_column2 && obj.y > m_ear_row1 && obj.y < m_ear_row2)
//                {
//                    break;
//                }*/

//            }
			result_defect.push_back(obj);
            message += QString::fromLocal8Bit(obj.name.c_str())  + ":size" + QString::number(obj.area) + "score" + QString::number(obj.threshold_score) + "\n";
		}
	}
	
    if(m_unuse_use_ear==1)
    {
        if(m_vector_rectangle_ear.size()!=m_vector_ear_standard.size())
        {
            message += "ear roi != ear standard";
            return 0;
        }
        for(int i=0;i<m_vector_rectangle_ear.size();i++)
        {
            QRectF qrectf = m_vector_rectangle_ear[i]->returnRect();
            int row1 = m_vector_rectangle_ear[i]->pos().y() + (int)qrectf.y();
            int column1 = m_vector_rectangle_ear[i]->pos().x() + (int)qrectf.x();
            int row2 = m_vector_rectangle_ear[i]->pos().y() + (int)(qrectf.y() + qrectf.height());
            int column2 = m_vector_rectangle_ear[i]->pos().x() + (int)(qrectf.x() + qrectf.width());
           

			int max_size_now=0;
            int ear_number = 0;
            for(auto result :result_all[0])
            {
				if (result.name != m_vector_ear_standard[i].name)
					continue;
				if (result.x > column2 || result.x < column1 || result.y > row2 || result.y < row1)
				{
					continue;
				}
				if (max_size_now < result.area)
				{
					max_size_now = result.area;
				}
                if(result.area>m_vector_ear_standard[i].threshold_size_min && result.area < m_vector_ear_standard[i].threshold_size_max)
                {
					result_ear.push_back(result);
					ear_number++;
                }
            }
            if(ear_number< m_vector_ear_standard[i].threshold_number)
            {

                message += m_vector_rectangle_ear[i]->m_message + "max_size:" + QString::number(max_size_now) +" error\n" ;
                return 0;

            }
        }
    }
	

	if (result_defect.size() > 0)
	{
		return 0;
	}
    return 1;

}

void Function_dl_3::detectionImage()
{
    if(m_image.empty())
       {
           QMessageBox::information(nullptr,"","no image");
           return;
       }

       QString message;


       bool state = detection(m_image, message);

	   if (state)
	   {
		   message = "OK" + message;
	   }
	   else
	   {
		   message = "NG" + message;
	   }

       Mat image_show;

       draw(m_image,image_show);

       QImage q_image = matToQImage(image_show);
       if (!q_image.isNull())
       {
           m_view->setImage(q_image, message);
       }

}

void Function_dl_3::draw(Mat image_in, Mat& image_out)
{
	
	image_out = image_in.clone();
	if (image_out.channels() == 1)
	{
		cvtColor(image_out, image_out, COLOR_GRAY2BGR);
	}
	for (auto obj : result_defect)
	{
		drawContours(image_out, obj.contour, -1, Scalar(0, 0, 255), 3);
	}
    result_defect.clear();

	for (auto obj : result_ear)
	{
		drawContours(image_out, obj.contour, -1, Scalar(0, 204, 204), 3);

	}
	result_ear.clear();
}

void Function_dl_3::loadParameter()
{
    try
    {
		int roi_number = m_qsettings->value(m_section + "/" + "roi_number", 0).toInt();
		if (roi_number > 0)
		{
			int i = 0;
			row1 = m_qsettings->value(m_section + "/" + "ROI" + QString::number(i) + "row1", 100).toInt();
			column1 = m_qsettings->value(m_section + "/" + "ROI" + QString::number(i) + "column1", 100).toInt();
			row2 = m_qsettings->value(m_section + "/" + "ROI" + QString::number(i) + "row2", 200).toInt();
			column2 = m_qsettings->value(m_section + "/" + "ROI" + QString::number(i) + "column2", 200).toInt();

			GraphicsShapeRectangleCirce* p = new GraphicsShapeRectangleCirce( column1, row1,  column2 - column1, row2 - row1, Qt::blue);
			p->setShapeType(0);
			p->setFilled(false);
			p->setZValue(101);
			m_view->m_scene->addItem(p);
			
			m_vector_graphics_shape_rectangle.push_back(p);
		}

        int ear_number = m_qsettings->value(m_section + "/" + "ear_number", 0).toInt();
        for(int i=0;i<ear_number;i++)
        {
            int m_ear_row1 = m_qsettings->value(m_section + "/" + "ear" + QString::number(i) + "row1", 100).toInt();
            int m_ear_column1 = m_qsettings->value(m_section + "/" + "ear" + QString::number(i) + "column1", 100).toInt();
            int m_ear_row2 = m_qsettings->value(m_section + "/" + "ear" + QString::number(i) + "row2", 200).toInt();
            int m_ear_column2 = m_qsettings->value(m_section + "/" + "ear" + QString::number(i) + "column2", 200).toInt();

            GraphicsShapeRectangleCirce* p = new GraphicsShapeRectangleCirce(m_ear_column1, m_ear_row1, m_ear_column2 - m_ear_column1, m_ear_row2 - m_ear_row1, Qt::darkYellow);

            p->m_message = "ear"+QString::number(i);
            p->setShapeType(0);
            p->setFilled(false);
            p->setZValue(102);
		
            m_view->m_scene->addItem(p);
			
            m_vector_rectangle_ear.push_back(p);
        }


		
        RetrainedModelFileName = m_qsettings->value(m_section + "/" + "RetrainedModelFileName","").toString();
        m_qlabel_model_path->setText(RetrainedModelFileName);

		m_unuse_use_ear = m_qsettings->value(m_section + "/" + "m_unuse_use_ear").toInt();
		m_qcombox_unuse_use_ear->setCurrentIndex(m_unuse_use_ear);

        save_dl_prar1(m_qwidget_dl_para1, m_vector_defect_standard);
		if (m_camera_index == 3 || m_camera_index == 4)
		{
			if(m_detection_index==0)
				save_dl_prar2(m_qwidget_dl_para2, m_vector_ear_standard);
		}
    }
    catch(exception& error)
    {
        QMessageBox::critical(nullptr,error.what() , m_section + "para error");
    }

    return ;
}

void Function_dl_3::saveParameter()
{
    try
        {

			m_qsettings->setValue(m_section + "/" + "roi_number", m_vector_graphics_shape_rectangle.size());
			if (m_vector_graphics_shape_rectangle.size() > 0)
			{
				int i = 0;
				QRectF qrectf = m_vector_graphics_shape_rectangle[i]->boundingRect();
				row1 = m_vector_graphics_shape_rectangle[i]->pos().y() + (int)qrectf.y();
				column1 = m_vector_graphics_shape_rectangle[i]->pos().x() + (int)qrectf.x();
				row2 = m_vector_graphics_shape_rectangle[i]->pos().y() + (int)(qrectf.y() + qrectf.height());
				column2 = m_vector_graphics_shape_rectangle[i]->pos().x() + (int)(qrectf.x() + qrectf.width());
				m_qsettings->setValue(m_section + "/" + "ROI" + QString::number(i) + "row1", row1);
				m_qsettings->setValue(m_section + "/" + "ROI" + QString::number(i) + "column1", column1);
				m_qsettings->setValue(m_section + "/" + "ROI" + QString::number(i) + "row2", row2);
				m_qsettings->setValue(m_section + "/" + "ROI" + QString::number(i) + "column2", column2);
			}

            m_qsettings->setValue(m_section + "/" + "ear_number", m_vector_rectangle_ear.size());

            for(int i=0;i<m_vector_rectangle_ear.size();i++)
            {
                QRectF qrectf = m_vector_rectangle_ear[i]->returnRect();
                int row1 = m_vector_rectangle_ear[i]->pos().y() + (int)qrectf.y();
                int column1 = m_vector_rectangle_ear[i]->pos().x() + (int)qrectf.x();
                int row2 = m_vector_rectangle_ear[i]->pos().y() + (int)(qrectf.y() + qrectf.height());
                int column2 = m_vector_rectangle_ear[i]->pos().x() + (int)(qrectf.x() + qrectf.width());
                m_qsettings->setValue(m_section + "/" + "ear" + QString::number(i)+"row1", row1);
                m_qsettings->setValue(m_section + "/" + "ear" + QString::number(i)+"column1", column1);
                m_qsettings->setValue(m_section + "/" + "ear" + QString::number(i)+"row2", row2);
                m_qsettings->setValue(m_section + "/" + "ear" + QString::number(i)+"column2", column2);
            }



            RetrainedModelFileName = m_qlabel_model_path->text();
            m_qsettings->setValue(m_section + "/" + "RetrainedModelFileName", RetrainedModelFileName);


			m_unuse_use_ear = m_qcombox_unuse_use_ear->currentIndex();
			m_qsettings->setValue(m_section + "/" + "m_unuse_use_ear", m_unuse_use_ear);

            save_dl_prar1(m_qwidget_dl_para1, m_vector_defect_standard);
			if ( m_camera_index == 3 || m_camera_index == 4)
			{
				if (m_detection_index == 0)
					save_dl_prar2(m_qwidget_dl_para2, m_vector_ear_standard);
			}

            if(m_vector_rectangle_ear.size()!=m_vector_ear_standard.size())
            {
                QMessageBox::information(nullptr,"","ear roi != ear standard");
            }
        }
        catch(exception& error)
        {
            QMessageBox::critical(nullptr,error.what() , m_section + "para error");
        }
}

bool Function_dl_3::showDialog()
{
    QImage q_image = matToQImage(m_image);
    m_view->setImage(q_image,"");
    return true;
}

void Function_dl_3::loadmodel()
{



    m_dl = new AIDll();
    string message;
    string para_path  = RetrainedModelFileName.toLocal8Bit().toStdString();
    QString name = "test";
    vector<string> m_vector_node;
    m_vector_node.push_back(name.toLocal8Bit().toStdString());


    if(false == m_dl->loadPorjectFiles(para_path,m_vector_node, 5472, 4400, 1,message))
        QMessageBox::information(nullptr,"ai", QString::fromStdString(message));
	else
	{
		vector_dl_3.push_back(m_dl);
		m_state = true;
	}
	
}

void Function_dl_3::save_dl_prar1(QWidgetDlPara1* roi_sqllite, vector<DefectStandard>& vector_defect_standard)
{
	roi_sqllite->submit();
	vector_defect_standard.clear();
    for (int j = 0; j < roi_sqllite->m_qsltablemodel->rowCount(); j++)
	{
		DefectStandard defect_standard;
		defect_standard.name = roi_sqllite->m_qsltablemodel->data(roi_sqllite->m_qsltablemodel->index(j, 1)).toString().toLocal8Bit().toStdString();
        defect_standard.threshold_score = roi_sqllite->m_qsltablemodel->data(roi_sqllite->m_qsltablemodel->index(j, 2)).toDouble();
        defect_standard.threshold_size = roi_sqllite->m_qsltablemodel->data(roi_sqllite->m_qsltablemodel->index(j, 3)).toDouble();
		vector_defect_standard.push_back(defect_standard);
	}
}

void Function_dl_3::save_dl_prar2(QWidgetDlPara2* roi_sqllite, vector<DetectionStandard>& vector_defect_standard)
{
    roi_sqllite->submit();
    m_vector_ear_standard.clear();
    for (int j = 0; j < roi_sqllite->m_qsltablemodel->rowCount(); j++)
    {
        DetectionStandard defect_standard;
        defect_standard.name = roi_sqllite->m_qsltablemodel->data(roi_sqllite->m_qsltablemodel->index(j, 1)).toString().toLocal8Bit().toStdString();
        defect_standard.threshold_score = roi_sqllite->m_qsltablemodel->data(roi_sqllite->m_qsltablemodel->index(j, 2)).toDouble();
        defect_standard.threshold_size_min = roi_sqllite->m_qsltablemodel->data(roi_sqllite->m_qsltablemodel->index(j, 3)).toDouble();
		defect_standard.threshold_size_max = roi_sqllite->m_qsltablemodel->data(roi_sqllite->m_qsltablemodel->index(j, 4)).toDouble();
        defect_standard.threshold_number = roi_sqllite->m_qsltablemodel->data(roi_sqllite->m_qsltablemodel->index(j, 5)).toDouble();;
        m_vector_ear_standard.push_back(defect_standard);
    }
}
